package com.common.utils.tool;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 描述：
 * 缓存工具类Caffeine
 *  <p>用于本地缓存，不能用于分布式环境</p>
 * @author xianggj
 * @Date 2021/8/12 9:47
 **/
public class CaffeineUtils {


    /**
     * 默认缓存30分钟
     */
    private static final int TIME = 30*60;

    /**
     * 线程对象
     */
    private static Cache<String, Object> cache = null;

    /**
     * 重新定义缓存
     * @param duration
     * @param maximumSize
     * @return
     */
    public static Cache<String, Object> createCache(long duration, long maximumSize){
        Cache<String, Object> caffeine = Caffeine.newBuilder()
                //最后一次写入后多久过期 这里不用最后一次访问后多久过期为了保证频繁刷新情况数据准确性
                .expireAfterWrite(duration, TimeUnit.SECONDS)
                .maximumSize(maximumSize)
                .build();
        cache = caffeine;
        return caffeine;
    }

    /**
     * 带刷新的缓存
     * @param duration
     * @param maximumSize
     * @return
     */
    public static Cache<String, Object> createRefreshCache(long duration, long maximumSize,
                                                           long refresh, CacheLoader<? super String, Object> loader){
        Cache<String, Object> caffeine = Caffeine.newBuilder()
                //最后一次写入后多久过期 这里不用最后一次访问后多久过期为了保证频繁刷新情况数据准确性
                .expireAfterWrite(duration, TimeUnit.SECONDS)
                //定义刷新周期 build 里面需要写刷新函数
                .refreshAfterWrite(refresh, TimeUnit.MINUTES)
                .maximumSize(maximumSize)
                .build(loader);
        cache = caffeine;
        return caffeine;
    }

    /**
     * 重新定义缓存
     *  5000 避免空间占用
     * @param duration
     * @return
     */
    public static Cache<String, Object> createCache(long duration){
        return createCache(duration, 5000);
    }

    /**
     * 获取缓存
     *  5 本地缓存5秒就够了 避免重复访问 又避免不能更新最新数据
     * @return
     */
    public static Cache<String, Object> getCache(){
        if (cache == null){
            //5秒保证单次请求内的多次调用
            cache = createCache(TIME);
        }
        return cache;
    }

    /**
     * 获取缓存
     * @param key String 类型
     * @return  Object对象
     */
    public static Object get(String key) {
        Cache<String, Object> cacheMap = getCache();
        return cacheMap.getIfPresent(key);
    }

    /**
     * 获取缓存 带默认值
     * @param key String 类型
     * @return  Object对象
     */
    public static Object get(String key, Object defaultValue) {
        Cache<String, Object> cacheMap = getCache();
        return cacheMap.get(key, t->defaultValue);
    }

    /**
     * 写入缓存
     * @param key String类型
     * @param value Object类型
     * @return void 对象
     */
    public static void put(String key, Object value) {
        Cache<String, Object> cacheMap = getCache();
        cacheMap.put(key, value);
    }

    /**
     * 写入缓存
     * @param map 写入map
     * @return void 对象
     */
    public static void putAll(Map<String, Object> map) {
        Cache<String, Object> cacheMap = getCache();
        cacheMap.putAll(map);
    }

    /**
     * 从缓存中移除
     * @param key String
     * @return 返回移除的值
     */
    public static Object remove(String key) {
        Cache<String, Object> cacheMap = getCache();
        Object ifPresent = cacheMap.getIfPresent(key);
        cacheMap.invalidate(key);
        return ifPresent;
    }

    /**
     * 从缓存中移除
     * @param key String
     * @return void
     */
    public static void invalidate(String key) {
        Cache<String, Object> cacheMap = getCache();
        cacheMap.invalidate(key);
    }

    /**
     * 判断是否存在
     * @param key
     * @return
     */
    public static boolean containKey(String key) {
        Object o = get(key);
        if (o == null){
            return false;
        }
        return true;
    }

}
